#!/bin/sh
#------------------------------------------------------------------------------
# =========                 |
# \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
#  \\    /   O peration     |
#   \\  /    A nd           | www.openfoam.com
#    \\/     M anipulation  |
#------------------------------------------------------------------------------
#     Copyright (C) 2019-2020 OpenCFD Ltd.
#------------------------------------------------------------------------------
# License
#     This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
#
# Script
#     makeSCOTCH
#
# Description
#     Build the SCOTCH and PTSCOTCH libraries, optionally build binaries
#
# ----------------------------------------------
# NO USER-CONFIGURABLE SETTINGS WITHIN THIS FILE
#------------------------------------------------------------------------------
# Run from third-party directory only
cd "${0%/*}" || exit
wmakeCheckPwd "$WM_THIRD_PARTY_DIR" 2>/dev/null || {
    echo "Error (${0##*/}) : not located in \$WM_THIRD_PARTY_DIR"
    echo "    Check your OpenFOAM environment and installation"
    exit 1
}
. etc/tools/ThirdPartyFunctions
#------------------------------------------------------------------------------
_foamConfig scotch  # Get SCOTCH_ARCH_PATH, SCOTCH_VERSION

scotchPACKAGE=${SCOTCH_VERSION:-scotch-system}

unset withMPI
case "$WM_MPLIB" in (*MPI*) [ "$FOAM_MPI" = dummy ] || withMPI=true ;; esac

#------------------------------------------------------------------------------
usage()
{
    exec 1>&2
    while [ "$#" -ge 1 ]; do echo "$1"; shift; done
    /bin/cat<<USAGE

Usage: ${0##*/} [OPTION] [libso] [scotch-VERSION]
options:
  -force        Force compilation, even if include/library already exists
                Also force build attempt of pt-scotch (mingw)
  -gcc          Force use of gcc/g++
  -bin          Create scotch binaries as well (experimental)
  -no-bin       Suppress creation of scotch binaries (default)
  -no-mpi       Suppress build of pt-scotch
  -help

* Compile SCOTCH
      $scotchPACKAGE

USAGE
    showDownloadHint SCOTCH
    exit 1
}
#------------------------------------------------------------------------------

unset optBinaries optForce

# Parse options
while [ "$#" -gt 0 ]
do
    case "$1" in
    '') ;;      # Ignore empty
    -h | -help) usage   ;;
    -gcc)       useGcc  ;;
    -force)     optForce=true ;;

    -bin)       optBinaries=true ;;
    -no-bin)    unset optBinaries ;;
    -no-mpi)    unset withMPI ;;

    scotch-[0-9]* | scotch-git | scotch_* )
        scotchPACKAGE="${1%%/}"
        unset SCOTCH_ARCH_PATH  # Avoid inconsistency
        ;;
    *)
        die "unknown option/argument: '$1'"
        ;;
    esac
    shift
done

[ -n "$scotchPACKAGE" ] || die "The scotch-VERSION was not specified"

# Nothing to build
if _foamIsNone "$scotchPACKAGE"
then
    echo "Using scotch-none (skip ThirdParty build of SCOTCH)"
    exit 0
elif _foamIsSystem "$scotchPACKAGE"
then
    echo "Using scotch-system"
    exit 0
fi

requireExtLibBin

#------------------------------------------------------------------------------

# Needs generalizing, but works fairly well
for scotchMakefile in \
    "OpenFOAM-$(uname -s)-${WM_COMPILER}.shlib" \
    "OpenFOAM-$(uname -s).shlib" \
    OpenFOAM-Linux.shlib \
;
do
    scotchMakefile="etc/makeFiles/scotch/Makefile.inc.$scotchMakefile"
    [ -f "$scotchMakefile" ] && break
done

# The relative link location within the "scotch/src/" directory
makefileInc="../../$scotchMakefile"

#------------------------------------------------------------------------------
#
# Build SCOTCH
#
#   SCOTCH_ARCH_PATH  : installation directory
#   SCOTCH_SOURCE_DIR : location of the original sources

SCOTCH_SOURCE_DIR="$sourceBASE/$scotchPACKAGE"
: "${SCOTCH_ARCH_PATH:=$installBASE$WM_SIZE_OPTIONS/$scotchPACKAGE}"

[ -d "$SCOTCH_SOURCE_DIR/src" ] || {
    echo "Missing sources: '$scotchPACKAGE'"
    showDownloadHint SCOTCH
    exit 2
}

echo
echo ========================================
echo "scotch decomposition ($scotchPACKAGE)"
echo "    Makefile.inc  : ${makefileInc##*/}"

# (serial) scotch
prefixDIR="$SCOTCH_ARCH_PATH"
binDIR="$prefixDIR"/bin
incDIR="$prefixDIR"/include
libDIR="$FOAM_EXT_LIBBIN"

# Test installation. May or may not have libscotcherrexit.so
if [ -z "$optForce" ] \
&& [ -f "$incDIR"/scotch.h ] \
&& haveLibso "$libDIR"/libscotch
then
    echo "    scotch include: $incDIR"
    echo "    scotch library: $libDIR"
elif [ -d "$SCOTCH_SOURCE_DIR" ]
then
(
    # Older versions ok, but scotch-6.0.5a cannot build in parallel.
    # Force serial build
    export WM_NCOMPPROCS=1
    echo "*** building scotch in serial ***"
    echo

    [ -f "$scotchMakefile" ] || {
        echo " Error: no such makefile: $scotchMakefile"
        exit 1
    }

    cd "$SCOTCH_SOURCE_DIR/src" || exit
    export GIT_DIR="$SCOTCH_SOURCE_DIR/.git" # Mask seeing our own git-repo
    rm -rf "$SCOTCH_ARCH_PATH"

    applyPatch "$scotchPACKAGE" ..      # patch at parent-level

    mkdir -p "$binDIR" 2>/dev/null
    mkdir -p "$incDIR" 2>/dev/null
    mkdir -p "$libDIR" 2>/dev/null

    if [ -f "$makefileInc" ]
    then
        rm -f Makefile.inc
        ln -s "$makefileInc" Makefile.inc
    fi
    [ -f Makefile.inc ] || {
        echo " Error: scotch needs an appropriate Makefile.inc"
        exit 1
    }

    export CCS="$(whichCC)"         # CCS (serial compiler)
    export CCP="$(whichMpicc)"      # CCP (parallel compiler) default=mpicc

    # Consistency for Intel-MPI and non-icc compilers
    [ -n "$I_MPI_CC" ] || export I_MPI_CC="$(whichCC)"

    # The make targets
    make_targets="libscotch"
    if [ "$optBinaries" = true ]
    then
        make_targets="$make_targets scotch"
    fi

    make realclean 2>/dev/null  # Extra safety
    make -j $WM_NCOMPPROCS $make_targets \
     && make \
        prefix="$prefixDIR" \
        bindir="$binDIR" \
        libdir="$libDIR" \
        includedir="$incDIR" \
        install

    rmdir "$binDIR" 2>/dev/null || true         # Remove empty bin/
    rmdir "${binDIR%/*}" 2>/dev/null || true    # ... and empty parent
    make realclean 2>/dev/null || true          # Failed cleanup is uncritical
) || warnBuildIssues SCOTCH
else
    warnNotFound SCOTCH
fi


# Build ptscotch when MPI (ThirdParty or system) is available

if [ "${withMPI}" != true ]
then
    # Report that the above tests failed and pass-through the failure
    echo "Skipping pt-scotch (no mpi)"
    exit 0
fi

# Known build issues for mingw (MS-MPI source code annotations)
case "$WM_COMPILER" in
(Mingw*)
    if [ -z "$optForce" ]
    then
        echo "Skipping pt-scotch - known compilation issues with $WM_COMPILER"
        exit 0
    else
        echo "Warning: pt-scotch - known compilation issues with $WM_COMPILER"
    fi
    ;;
esac


# Build ptscotch if normal scotch was built (has include and library)
# (reuse prefix/include/lib dirs set above)
if [ -f "$incDIR"/scotch.h ] \
&& haveLibso "$libDIR"/libscotch
then
    echo
    echo ========================================
    echo "pt-scotch decomposition ($scotchPACKAGE with $FOAM_MPI)"
else
    # Report that the above tests failed and pass-through the failure
    echo "Skipping pt-scotch - no <scotch.h> found"
    exit 2
fi

# (parallel) pt-scotch
prefixDIR="$SCOTCH_ARCH_PATH"
binDIR="$prefixDIR/bin/$FOAM_MPI"
incDIR="$prefixDIR/include/$FOAM_MPI"
libDIR="$FOAM_EXT_LIBBIN/$FOAM_MPI"

if [ -z "$optForce" ] \
&& [ -f "$incDIR"/ptscotch.h ] \
&& haveLibso "$libDIR"/libptscotch
then
    echo "    ptscotch include: $incDIR"
    echo "    ptscotch library: $libDIR"
else
(
    # Older versions ok, but scotch-6.0.5a cannot build in parallel.
    # Force serial build
    export WM_NCOMPPROCS=1
    echo "*** building pt-scotch in serial ***"

    [ -f "$scotchMakefile" ] || {
        echo " Error: no such makefile: $scotchMakefile"
        exit 1
    }

    cd "$SCOTCH_SOURCE_DIR/src" || exit
    export GIT_DIR="$SCOTCH_SOURCE_DIR/.git" # Mask seeing our own git-repo
    echo

    mkdir -p "$binDIR" 2>/dev/null
    mkdir -p "$incDIR" 2>/dev/null
    mkdir -p "$libDIR" 2>/dev/null

    if [ -f "$makefileInc" ]
    then
        rm -f Makefile.inc
        ln -s "$makefileInc" Makefile.inc
    fi
    [ -f Makefile.inc ] || {
        echo " Error: ptscotch needs an appropriate Makefile.inc"
        exit 1
    }

    export CCS="$(whichCC)"     # CCS (serial compiler)
    export CCP="$(whichMpicc)"  # CCP (parallel compiler) default=mpicc

    # Consistency for Intel-MPI and non-icc compilers
    [ -n "$I_MPI_CC" ] || export I_MPI_CC="$(whichCC)"

    # The make targets. No simple means of handling mpi-specific binaries
    make_targets="libptscotch"
    if [ "$optBinaries" = true ]
    then
        make_targets="$make_targets ptscotch"
    fi

    make realclean 2>/dev/null  # Extra safety
    make -j $WM_NCOMPPROCS $make_targets \
     && make \
        prefix="$prefixDIR" \
        bindir="$binDIR" \
        libdir="$libDIR" \
        includedir="$incDIR" \
        install

    rmdir "$binDIR" 2>/dev/null || true         # Remove empty bin/
    rmdir "${binDIR%/*}" 2>/dev/null || true    # ... and empty parent
    make realclean 2>/dev/null || true          # Failed cleanup is uncritical
) || warnBuildIssues PTSCOTCH
fi

# Verify existence of ptscotch include
[ -f "$SCOTCH_ARCH_PATH/include/$FOAM_MPI/ptscotch.h" ] || {
    echo
    echo "    WARNING: required include file 'ptscotch.h' not found!"
}

# Could now remove $SCOTCH_SOURCE_DIR/src/Makefile.inc

#------------------------------------------------------------------------------
